package ide.ccf.ccproject.launch;

import ide.ccf.ccproject.CCFNature;
import ide.ccf.ccproject.CCFProject;
import ide.ccf.ccproject.common.Utils;

import java.util.HashMap;
import java.util.Map;
import java.util.Vector;

import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.debug.mi.core.IMILaunchConfigurationConstants;
import org.eclipse.cdt.launch.AbstractCLaunchDelegate;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationListener;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.ISourceLocator;
import org.eclipse.debug.core.sourcelookup.AbstractSourceLookupDirector;
import org.eclipse.debug.core.sourcelookup.ISourceContainer;
import org.eclipse.debug.core.sourcelookup.containers.DirectorySourceContainer;


/**
 * 项目启动配置结果
 *
 */
class LaunchConfigResult 
{
	public ILaunchConfiguration config;
	public IProject project;
}

/**
 * CCF项目启动配置类
 *
 */
public class LaunchConfig implements ILaunchConfigurationListener
{
	/**
	 * 获取项目启动配置
	 * @param pro
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "deprecation", "unchecked" })
	private static ILaunchConfiguration[] getLaunchConfigurations(IProject pro) 
	{
		Vector result = new Vector();
		try 
		{
			ILaunchConfiguration[] configs = DebugPlugin.getDefault().getLaunchManager().getLaunchConfigurations();
			for (int i=0; i<configs.length; ++i) 
			{
				String projectName = AbstractCLaunchDelegate.getProjectName(configs[i]);
				
				if (projectName != null)
				{
					projectName = projectName.trim();
					if (projectName.length() > 0) 
					{
						IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
						
						if (project == pro)
							result.add(configs[i]);
					}
				}
			}
		} 
		catch (CoreException e) 
		{
			e.printStackTrace();
		}
		
		return (ILaunchConfiguration[])result.toArray(new ILaunchConfiguration[result.size()]);
	}
	
	/**
	 * 更新启动路径
	 * @param pro
	 * @param prepend
	 * @param remove
	 */
	public static void updateLaunchPaths(IProject pro, String prepend, String remove) 
	{
		ILaunchConfiguration[] configs = getLaunchConfigurations(pro);
		
		for (int i = 0; i < configs.length; ++i) 
		{
			updateConfigPath(configs[i], prepend, remove);
		}
	}

	/**
	 * 更新配置路径
	 * @param configuration
	 * @param prepend
	 * @param remove
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void updateConfigPath(ILaunchConfiguration configuration, String prepend, String remove) 
	{
		try 
		{
			ILaunchConfigurationWorkingCopy config = configuration.getWorkingCopy();
			Map m = config.getAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, new HashMap());
			String path = Utils.createPath((String)m.get("PATH"), prepend, remove);
			
			m.put("PATH", path);
			config.setAttribute(ILaunchManager.ATTR_ENVIRONMENT_VARIABLES, m);
			config.doSave();
			
			updateDebugSources(configuration, prepend, remove);
		} 
		catch (CoreException e) 
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 更新
	 * @param configuration
	 * @param prepend
	 * @param remove
	 * @throws CoreException
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	private static void updateDebugSources(ILaunchConfiguration configuration, String prepend, String remove) throws CoreException 
	{
		IPath pold = null;
		
		if (remove != null) 
		{
			pold = new Path(remove).removeLastSegments(1);
			pold = pold.append("src");
		}
		
		if (prepend == null)
			return;
		
		IPath pnew = new Path(prepend).removeLastSegments(1);
		pnew = pnew.append("src");
		
		String memento = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, (String)null);
		String type = configuration.getAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, (String)null);
		
		if (type == null)
			type = configuration.getType().getSourceLocatorId();
		
		if(type == null)
			return;
		
		ISourceLocator locator = DebugPlugin.getDefault().getLaunchManager().newSourceLocator(type);
		AbstractSourceLookupDirector fLocator = (AbstractSourceLookupDirector)locator;	
		
		if (memento == null) 
		{
			fLocator.initializeDefaults(configuration);
		} 
		else 
		{
			fLocator.initializeFromMemento(memento, configuration);				 
		}

		Vector newlist = new Vector();
		ISourceContainer[] containers = fLocator.getSourceContainers();
		
		for (int i = 0; i < containers.length; ++i) 
		{
			ISourceContainer c = containers[i];
			
			if (pold != null && c instanceof DirectorySourceContainer) 
			{
				DirectorySourceContainer dc = (DirectorySourceContainer)c;
				
				if (dc.getDirectory().getPath().compareTo(pold.toFile().getPath()) != 0)
					newlist.add(dc);
			} 
			else 
			{
				newlist.add(c);
			}
		}
		
		newlist.add(new DirectorySourceContainer(pnew, true));
		
		ILaunchConfigurationWorkingCopy config = configuration.getWorkingCopy();
		
		fLocator.setSourceContainers((ISourceContainer[])newlist.toArray(new ISourceContainer[newlist.size()]));
					
		config.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_MEMENTO, fLocator.getMemento());
		config.setAttribute(ILaunchConfiguration.ATTR_SOURCE_LOCATOR_ID, fLocator.getId());
		config.doSave();
	}

	/**
	 * 启动配置添加
	 */
	@SuppressWarnings("deprecation")
	public void launchConfigurationAdded(ILaunchConfiguration configuration) 
	{
		try 
		{
			ICProject pro = AbstractCLaunchDelegate.getCProject(configuration);
			
			if (pro == null || !pro.getProject().hasNature(CCFNature.NATURE_ID))
				return;
			
			String dir = (new CCFProject(pro.getProject())).getBinPath();
			updateConfigPath(configuration, dir, null);

			setStandardWindowsCommandFactory(configuration);			
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		}
	}
	
	/**
	 * 设置标准窗口命令Factory
	 * @param configuration
	 */
	private void setStandardWindowsCommandFactory(ILaunchConfiguration configuration)	
	{
		if (Platform.getOS().compareTo("win32") != 0)
			return;

		try 
		{
			ILaunchConfigurationWorkingCopy config;
			config = configuration.getWorkingCopy();
			config.setAttribute(IMILaunchConfigurationConstants.ATTR_DEBUGGER_COMMAND_FACTORY, "org.eclipse.cdt.debug.mi.core.standardWinCommandFactory");
			config.doSave();
		} 
		catch (CoreException e) 
		{
			e.printStackTrace();
		}
	}

	/**
	 * 启动配置改变事件
	 */
	public void launchConfigurationChanged(ILaunchConfiguration configuration) 
	{
		
	}
	
	/**
	 * 启动配置删除事件
	 */
	public void launchConfigurationRemoved(ILaunchConfiguration configuration) 
	{
		
	}
}